#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commdlg.h>
#include <stdio.h>
#include <vector>
#include <string>
#include <commctrl.h>
#include <objbase.h>

// 移除控制台窗口
#pragma comment(linker, "/subsystem:windows /entry:wWinMainCRTStartup")
// miniaudio配置 
#define MINIAUDIO_IMPLEMENTATION
#define MA_ENABLE_DECODING 1
#define MA_DEBUG_OUTPUT 1 // 启用调试输出
#include "miniaudio.h"

// 链接必要的库
#pragma comment(lib, "comctl32.lib")
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "comdlg32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "user32.lib")

// 修改全局变量
ma_engine g_engine; // 使用ma_engine代替直接设备管理
ma_sound g_sound;
BOOL g_isPlaying = FALSE;
BOOL g_isPaused = FALSE;
ma_uint64 g_totalFrames = 0;
ma_uint64 g_currentFrame = 0;
char g_filePath[MAX_PATH] = "";

HWND g_hwndPlay, g_hwndPause, g_hwndStop, g_hwndOpen;
HWND g_hwndProgress, g_hwndTimeLabel, g_hwndPlaylist, g_hwndPrev, g_hwndNext;
HWND g_mainWindow;
// CRITICAL_SECTION g_audioCritSec; // 临界区，保护音频数据访问

// 播放列表相关
struct PlaylistItem
{
    std::string path;
    std::string name;
};
std::vector<PlaylistItem> g_playlist;
int g_currentTrackIndex = -1;
// 修改音频初始化
BOOL InitializeAudio()
{
    ma_result result;
    ma_engine_config engineConfig = ma_engine_config_init();
    engineConfig.noDevice = MA_FALSE;
    engineConfig.channels = 0;   // 使用默认通道数
    engineConfig.sampleRate = 0; // 使用默认采样率

    result = ma_engine_init(&engineConfig, &g_engine);
    if (result != MA_SUCCESS)
    {
        char errMsg[256];
        sprintf_s(errMsg, "无法初始化音频引擎 (错误码: %d)", result);
        MessageBoxA(NULL, errMsg, "初始化失败", MB_ICONERROR);
        return FALSE;
    }

    return TRUE;
}

// 修改StopPlayback函数
void StopPlayback()
{
    if (g_isPlaying || g_isPaused)
    {
        ma_sound_stop(&g_sound);
        ma_sound_uninit(&g_sound);
    }

    g_isPlaying = FALSE;
    g_isPaused = FALSE;
    g_currentFrame = 0;
    g_totalFrames = 0;

    // 更新UI
    SendMessage(g_hwndProgress, PBM_SETPOS, 0, 0);
    SetWindowTextA(g_hwndTimeLabel, "0:00 / 0:00");
}

// 修改StartPlayback函数
void StartPlayback(const char *filePath)
{
    if (filePath == NULL || *filePath == '\0')
    {
        MessageBoxA(NULL, "无效的文件路径", "错误", MB_ICONERROR);
        return;
    }

    // 先停止当前播放
    StopPlayback();

    ma_result result;

    // 初始化声音
    result = ma_sound_init_from_file(&g_engine, filePath, 0, NULL, NULL, &g_sound);
    if (result != MA_SUCCESS)
    {
        char errMsg[256];
        sprintf_s(errMsg, "无法加载音频文件 (错误码: %d)\n请确保文件格式受支持", result);
        MessageBoxA(NULL, errMsg, "加载失败", MB_ICONERROR);
        return;
    }

    // 开始播放
    result = ma_sound_start(&g_sound);
    if (result != MA_SUCCESS)
    {
        char errMsg[256];
        sprintf_s(errMsg, "无法开始播放 (错误码: %d)", result);
        MessageBoxA(NULL, errMsg, "播放失败", MB_ICONERROR);
        ma_sound_uninit(&g_sound);
        return;
    }

    g_isPlaying = TRUE;
    g_isPaused = FALSE;
    strcpy_s(g_filePath, MAX_PATH, filePath);

    // 获取声音长度
    ma_uint64 lengthInFrames;
    if (ma_sound_get_length_in_pcm_frames(&g_sound, &lengthInFrames) == MA_SUCCESS)
    {
        g_totalFrames = lengthInFrames;
    }
    else
    {
        g_totalFrames = 0;
    }
    g_currentFrame = 0;

    // 更新窗口标题
    char title[MAX_PATH + 20];
    const char *fileName = strrchr(filePath, '\\');
    if (fileName == NULL)
        fileName = strrchr(filePath, '/');
    fileName = (fileName != NULL) ? fileName + 1 : filePath;
    sprintf_s(title, "Music Player - %s", fileName);
    SetWindowTextA(g_mainWindow, title);

    // 启用控制按钮
    EnableWindow(g_hwndPlay, TRUE);
    EnableWindow(g_hwndPause, TRUE);
    EnableWindow(g_hwndStop, TRUE);
}

// 格式化时间
std::string FormatTime(ma_uint64 frames, ma_uint32 sampleRate)
{
    if (sampleRate == 0)
        return "0:00";
    int totalSeconds = static_cast<int>(frames / sampleRate);
    int minutes = totalSeconds / 60;
    int seconds = totalSeconds % 60;

    char buffer[16];
    sprintf_s(buffer, "%d:%02d", minutes, seconds);
    return std::string(buffer);
}
// 修改UpdateProgressDisplay函数
void UpdateProgressDisplay()
{
    if (!g_isPlaying && !g_isPaused) {
        return;
    }

    ma_uint64 currentFrame = 0;
    ma_uint32 sampleRate = ma_engine_get_sample_rate(&g_engine);
    
    if (g_isPlaying || g_isPaused) {
        ma_sound_get_cursor_in_pcm_frames(&g_sound, &currentFrame);
        g_currentFrame = currentFrame;
    }

    if (g_totalFrames > 0) {
        int progress = static_cast<int>((static_cast<double>(currentFrame) / g_totalFrames) * 1000);
        SendMessage(g_hwndProgress, PBM_SETPOS, progress, 0);
    }
    
    std::string timeText = FormatTime(currentFrame, sampleRate) + " / ";
    if (g_totalFrames > 0) {
        timeText += FormatTime(g_totalFrames, sampleRate);
    } else {
        timeText += "∞";
    }
    SetWindowTextA(g_hwndTimeLabel, timeText.c_str());
}

// 打开文件对话框
void OpenFileDialog(BOOL addToPlaylist = FALSE)
{
    OPENFILENAMEA ofn;
    char szFile[MAX_PATH * 100] = "";

    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = g_mainWindow;
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = sizeof(szFile);
    ofn.lpstrFilter = "音频文件 (*.wav;*.mp3;*.flac)\0*.wav;*.mp3;*.flac\0所有文件 (*.*)\0*.*\0";
    ofn.nFilterIndex = 1;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER;

    if (GetOpenFileNameA(&ofn))
    {
        std::vector<std::string> files;
        char *p = szFile;
        std::string directory = p;
        p += directory.length() + 1;

        if (*p)
        {
            while (*p)
            {
                files.push_back(directory + "\\" + p);
                p += strlen(p) + 1;
            }
        }
        else
        {
            files.push_back(szFile);
        }

        for (const auto &file : files)
        {
            if (addToPlaylist)
            {
                PlaylistItem item;
                item.path = file;

                size_t lastSlash = file.find_last_of("\\/");
                item.name = (lastSlash != std::string::npos) ? file.substr(lastSlash + 1) : file;

                g_playlist.push_back(item);
                SendMessageA(g_hwndPlaylist, LB_ADDSTRING, 0, (LPARAM)item.name.c_str());

                if (g_currentTrackIndex == -1)
                {
                    g_currentTrackIndex = 0;
                    SendMessageA(g_hwndPlaylist, LB_SETCURSEL, 0, 0);
                }
            }
            else
            {
                StartPlayback(file.c_str());
                break;
            }
        }
    }
}

// 播放下一首
void PlayNextTrack()
{
    if (g_playlist.empty())
        return;

    g_currentTrackIndex = (g_currentTrackIndex + 1) % g_playlist.size();
    SendMessageA(g_hwndPlaylist, LB_SETCURSEL, g_currentTrackIndex, 0);
    StartPlayback(g_playlist[g_currentTrackIndex].path.c_str());
}

// 播放上一首
void PlayPrevTrack()
{
    if (g_playlist.empty())
        return;

    g_currentTrackIndex = (g_currentTrackIndex - 1 + g_playlist.size()) % g_playlist.size();
    SendMessageA(g_hwndPlaylist, LB_SETCURSEL, g_currentTrackIndex, 0);
    StartPlayback(g_playlist[g_currentTrackIndex].path.c_str());
}

// 窗口过程
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CREATE:
    {
        int btnWidth = 80, btnHeight = 30, margin = 10;
        int yPos = margin;

        g_hwndOpen = CreateWindowExA(0, "BUTTON", "Open",
                                     WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                     margin, yPos, btnWidth, btnHeight,
                                     hwnd, (HMENU)1, NULL, NULL);

        g_hwndPlay = CreateWindowExA(0, "BUTTON", "Play",
                                     WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                     margin + btnWidth + margin, yPos, btnWidth, btnHeight,
                                     hwnd, (HMENU)2, NULL, NULL);

        g_hwndPause = CreateWindowExA(0, "BUTTON", "Pause",
                                      WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                      margin + (btnWidth + margin) * 2, yPos, btnWidth, btnHeight,
                                      hwnd, (HMENU)3, NULL, NULL);

        g_hwndStop = CreateWindowExA(0, "BUTTON", "Stop",
                                     WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                     margin + (btnWidth + margin) * 3, yPos, btnWidth, btnHeight,
                                     hwnd, (HMENU)4, NULL, NULL);

        g_hwndPrev = CreateWindowExA(0, "BUTTON", "Previous",
                                     WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                     margin + (btnWidth + margin) * 4, yPos, btnWidth, btnHeight,
                                     hwnd, (HMENU)5, NULL, NULL);

        g_hwndNext = CreateWindowExA(0, "BUTTON", "Next",
                                     WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                     margin + (btnWidth + margin) * 5, yPos, btnWidth, btnHeight,
                                     hwnd, (HMENU)6, NULL, NULL);

        yPos += btnHeight + margin;
        g_hwndProgress = CreateWindowExA(0, PROGRESS_CLASS, "",
                                         WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
                                         margin, yPos, 400, 20,
                                         hwnd, (HMENU)7, NULL, NULL);

        SendMessage(g_hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, 1000));
        SendMessage(g_hwndProgress, PBM_SETPOS, 0, 0);

        g_hwndTimeLabel = CreateWindowExA(0, "STATIC", "0:00 / 0:00",
                                          WS_CHILD | WS_VISIBLE | SS_CENTER,
                                          410, yPos, 80, 20,
                                          hwnd, (HMENU)8, NULL, NULL);

        yPos += 30;
        g_hwndPlaylist = CreateWindowExA(0, "LISTBOX", "",
                                         WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_NOTIFY,
                                         margin, yPos, 460, 150,
                                         hwnd, (HMENU)9, NULL, NULL);

        EnableWindow(g_hwndPlay, FALSE);
        EnableWindow(g_hwndPause, FALSE);
        EnableWindow(g_hwndStop, FALSE);
        EnableWindow(g_hwndPrev, FALSE);
        EnableWindow(g_hwndNext, FALSE);
        break;
    }

    case WM_COMMAND:
    {
        switch (LOWORD(wParam))
        {
        case 1:
            OpenFileDialog(TRUE);
            if (!g_playlist.empty())
            {
                EnableWindow(g_hwndPlay, TRUE);
                EnableWindow(g_hwndPause, TRUE);
                EnableWindow(g_hwndStop, TRUE);
                EnableWindow(g_hwndPrev, TRUE);
                EnableWindow(g_hwndNext, TRUE);
            }
            break;

            // 修改暂停/播放逻辑
        case 2: // 播放
            if (!g_isPlaying && g_filePath[0] != '\0')
            {
                if (g_isPaused)
                {
                    ma_sound_start(&g_sound);
                    g_isPlaying = TRUE;
                    g_isPaused = FALSE;
                }
                else
                {
                    StartPlayback(g_filePath);
                }
            }
            break;

        case 3: // 暂停
            if (g_isPlaying)
            {
                ma_sound_stop(&g_sound);
                g_isPlaying = FALSE;
                g_isPaused = TRUE;
            }
            break;

        case 4:
            StopPlayback();
            break;

        case 5:
            PlayPrevTrack();
            break;

        case 6:
            PlayNextTrack();
            break;

        case 9:
            if (HIWORD(wParam) == LBN_DBLCLK)
            {
                int index = SendMessageA(g_hwndPlaylist, LB_GETCURSEL, 0, 0);
                if (index != LB_ERR)
                {
                    g_currentTrackIndex = index;
                    StartPlayback(g_playlist[index].path.c_str());
                }
            }
            break;
        }
        break;
    }

    case WM_TIMER:
        if (wParam == 1)
        {
            UpdateProgressDisplay();
        }
        break;

    case WM_USER:
        StopPlayback();
        if (!g_playlist.empty())
        {
            PlayNextTrack();
        }
        break;

    // 在程序退出时清理音频资源
    case WM_DESTROY:
          StopPlayback();
          ma_engine_uninit(&g_engine);
          KillTimer(hwnd, 1);
          PostQuitMessage(0);
         break;

    default:
        return DefWindowProcA(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

// 主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{ 
    // 初始化音频引擎
    if (!InitializeAudio()) {
        return 0;
    }
    
    const char CLASS_NAME[] = "AudioPlayerClass";

    // 初始化通用控件
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_PROGRESS_CLASS;
    InitCommonControlsEx(&icex);

    // 初始化COM
    CoInitialize(NULL);

    // 注册窗口类
    WNDCLASSA wc = {0};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

    RegisterClassA(&wc);

    // 创建主窗口
    g_mainWindow = CreateWindowExA(
        0,
        CLASS_NAME,
        "music player",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 600, 400,
        NULL, NULL, hInstance, NULL);

    if (g_mainWindow == NULL)
    {
        CoUninitialize();
        return 0;
    }

    ShowWindow(g_mainWindow, nCmdShow);
    UpdateWindow(g_mainWindow);

    // 设置定时器
    SetTimer(g_mainWindow, 1, 500, NULL);

    // 消息循环
    MSG msg = {0};
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    // 清理资源
    KillTimer(g_mainWindow, 1);
    CoUninitialize();
    return 0;
}
